<?php

namespace App\Logics;


use App\Models\SiteSms;
use App\Models\User;
use App\Service\Base\Logic;
use App\Service\WeChat\OpenWx;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;

class AccountLogic extends Logic
{

    // 登录注册操作

    // 获取 token
    public function token()
    {
        $uid = $this->option()->getData('uid', 0, 'intval');
        if(empty($uid)){
            return $this->_returnFail('token_of_specified_user');
        }

        $userDb = new User();
        $field  = ['id', 'username', 'mobile', 'status', 'head_img', 'mobile', 'nickname'];
        $info   = $userDb->where(['id' => $uid])->first();
        if(empty($info)){
            return $this->_returnFail('user_has_no_exist');
        }
        if($info->status === 0){
            return $this->_returnFail('user_is_disabled');
        }

        $info   = $info->toArray();
        $token  = Crypt::encryptString(json_encode($info, JSON_UNESCAPED_UNICODE));
        $result = ['token' => $token, 'user' => $info,];

        return $result;
    }


    // 登录：用户名 + 验证码（只登录，不注册）
    public function userLogin()
    {
        $option   = $this->option();
        $username = $option->getData('username', null, 'trim');
        $password = $option->getData('password', null, 'trim');
        $mobile   = $option->getData('mobile', null, 'trim');
        $captcha  = $option->getData('captcha', null, 'trim');  // 验证码（短信验证码）
        if(empty($username)){
            return $this->_returnFail('enter_the_username');
        }
        if(empty($password)){
            return $this->_returnFail('enter_the_password');
        }
        /*if(empty($captcha)){
            return $this->_returnFail('enter_the_verification_code');
        }*/

        // 验证验证码
        /*// var_dump(Session::all());  // 前台没有验证码的session 输出所有的session，没有找到有对应验证码
        //if(!empty($login_code)){ }
        $login_code = Session::get('session_code');
        if((!empty($captcha)) && ($captcha != strtolower($login_code))){
            return $this->_returnFail('verification_code_is_wrong');
        }*/

        // 验证验证码  数据库
        if(!empty($captcha)){
            $codeWhere = [["email", '=', $username], ["ctime", '>=', strtotime("today")], ['status', '=', 0]];
            $smsDb     = new SiteSms();
            $lists     = $smsDb->isCache(false)->getList($codeWhere, 1, 'id DESC');
            if(empty($lists)){
                return $this->_returnFail('verification_code_is_wrong');
            }
            if($lists[0]['ctime'] + 600 < LARAVEL_TIME){
                return $this->_returnFail('verification_code_timed_out');
            }
            if($lists[0]['code'] != $captcha){
                return $this->_returnFail('verification_code_is_wrong');
            }

            // 使验证明失效
            $smsDb->where('id', $lists[0]['id'])->update(['status' => 1]);
        }

        // 判断是否是邮箱登录
        $type = 'loginname';
        if(strpos($username, '@') !== false){
            $type = 'email';
        }

        // 获取登录的用户信息
        $userDb = new User();
        $info   = $userDb->login($username, $password, $type);
        if($info === false){
            return $this->_returnFail($userDb->getError());
        }

        // token
        $info = is_object($info) ? $info->toArray() : $info;
        unset($info['password']);
        $token  = Crypt::encryptString(json_encode($info, JSON_UNESCAPED_UNICODE));
        $result = ['token' => $token, 'user' => $info,];

        return $result;
    }

    // 登录：手机号 + 验证码（只登录，不注册）
    public function mobileLogin()
    {
        $option   = $this->option();
        $username = $option->getData('username', null, 'trim');
        $password = $option->getData('password', null, 'trim');
        $mobile   = $option->getData('mobile', null, 'trim');
        $captcha  = $option->getData('captcha', null, 'trim');  // 验证码（短信验证码）
        if(empty($mobile)){
            return $this->_returnFail('enter_your_mobile_number');
        }
        if(empty($password)){
            return $this->_returnFail('enter_the_password！');
        }
        if(empty($captcha)){
            return $this->_returnFail('enter_the_verification_code');
        }

        /*// 验证验证码
        $login_code = Session::get('session_code');
        // var_dump(Session::all());  // 前台没有验证码的session 输出所有的session，没有找到有对应验证码
        //if(!empty($login_code)){ }
        if($captcha != strtolower($login_code)){
            return $this->_returnFail('verification_code_is_wrong');
        }*/

        // 验证验证码  数据库
        if(!empty($captcha)){
            $codeWhere = [["email", '=', $username], ["ctime", '>=', strtotime("today")], ['status', '=', 0]];
            $smsDb     = new SiteSms();
            $lists     = $smsDb->isCache(false)->getList($codeWhere, 1, 'id DESC');
            if(empty($lists)){
                return $this->_returnFail('verification_code_is_wrong');
            }
            if($lists[0]['ctime'] + 600 < LARAVEL_TIME){
                return $this->_returnFail('verification_code_timed_out');
            }
            if($lists[0]['code'] != $captcha){
                return $this->_returnFail('verification_code_is_wrong');
            }

            // 使验证明失效
            $smsDb->where('id', $lists[0]['id'])->update(['status' => 1]);
        }

        // 获取登录的用户信息
        $userDb = new User();
        $info   = $userDb->login($mobile, $password, 'mobile');
        if($info === false){
            return $this->_returnFail($userDb->getError());
        }

        $info = is_object($info) ? $info->toArray() : $info;
        unset($info['password']);
        $token  = Crypt::encryptString(json_encode($info, JSON_UNESCAPED_UNICODE));
        $result = ['token' => $token, 'user' => $info,];

        return $result;
    }

    // 邮箱与密码注册
    public function newReg()
    {
        $option   = $this->option();
        $username = $option->getData('username', null, 'trim');
        $email    = $option->getData('email', null, 'trim');
        $password = $option->getData('password', null, 'trim');
        $mobile   = $option->getData('mobile', null, 'trim');
        $captcha  = $option->getData('captcha', null, 'trim');  // 验证码（短信验证码）
        if(empty($email)){
            return $this->_returnFail('enter_the_email');
        }
        if(empty($password)){
            return $this->_returnFail('enter_the_password');
        }
        if(empty($captcha)){
            return $this->_returnFail('enter_the_verification_code');
        }

        // 验证验证码
        // var_dump(Session::all());  // 前台没有验证码的session 输出所有的session，没有找到有对应验证码
        //if(!empty($login_code)){ }
        /*$session_name = 'session_code';
        $login_code   = Session::get($session_name);
        if((!empty($captcha)) && ($captcha != strtolower($login_code))){
            return $this->_returnFail('verification_code_is_wrong');
        }
        // 删除验证码
        Session::put($session_name, null);*/

        // 验证验证码  数据库
        if(!empty($captcha)){
            $codeWhere = [["email", '=', $email], ["ctime", '>=', strtotime("today")], ['status', '=', 0]];
            $smsDb     = new SiteSms();
            $lists     = $smsDb->isCache(false)->getList($codeWhere, 1, 'id DESC');
            if(empty($lists)){
                return $this->_returnFail('verification_code_is_wrong');
            }
            if($lists[0]['ctime'] + 600 < LARAVEL_TIME){
                return $this->_returnFail('verification_code_timed_out');
            }
            if($lists[0]['code'] != $captcha){
                return $this->_returnFail('verification_code_is_wrong');
            }

            // 使验证明失效
            $smsDb->where('id', $lists[0]['id'])->update(['status' => 1]);
        }

        // 判断是否是邮箱登录
        /*$type = 'loginname';
        if(strpos($username, '@') !== false){
            $type = 'email';
        }*/


        // 查询用户信息
        $userDb = new User();
        $where  = [['email', '=', $email], ['status', '>=', 0]];
        $info   = $userDb->where($where)->first();
        if($info){
            /*if($type == 'email'){
                return $this->_returnFail("email_has_exist");
            } else{
                return $this->_returnFail("loginname_has_exist");
            }*/
            return $this->_returnFail("email_has_exist");
        }

        // 如果没有 则注册
        $salt  = Str::random(4);
        $_pass = $userDb->add_md5($password, $salt);  // 密码
        $data  = ['email' => $email, 'salt' => $salt, 'password' => $_pass, 'last_ip' => $option->getIp(), 'last_time' => LARAVEL_TIME, 'status' => 1,];
        $uid   = $userDb->oneAdd($data);

        // 重新查询
        $info = $userDb->isCache(true)->oneFind($where);
        $info = is_object($info) ? $info->toArray() : $info;
        unset($info['password']);

        // token
        $token  = Crypt::encryptString(json_encode($info, JSON_UNESCAPED_UNICODE));
        $result = ['token' => $token, 'user' => $info,];

        return $result;
    }

    // 发送邮件
    public function sendMail()
    {
        $option = $this->option();
        $type   = $option->getData('type', null, 'trim');  // login:登录 reg:注册 forgot:忘记密码
        $email  = $option->getData('email', null, 'trim');
        if(empty($email)){
            return $this->_returnFail('please_specify_the_email_address_to_send');
        }

        // 判断是否是邮箱
        if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
            return $this->_returnFail('please_specify_the_email_address_to_send');
        }

        // 判断邮箱是否存在
        $userDb = new User();
        $where  = [['email', '=', $email], ['status', '>=', 0]];
        $info   = $userDb->where($where)->first();
        if(in_array($type, ['login', 'forgot'])){
            // 登录：邮箱必须存在
            if(empty($info)){
                return $this->_returnFail('email_has_not_exist');
            }
        } elseif($type == 'reg'){
            // 登录：邮箱已经存在
            if($info){
                return $this->_returnFail('email_has_exist');
            }
        }

        $timeout = 60; // 超时时间 60秒
        $timeout = 6; // 超时时间 60秒
        $times   = 50; // 一个号一天限制10次
        // 验证码
        $name = 'session_code';
        $num  = 6;
        $code = strtolower(random($num));
        if(in_array($email, ['1758958047@qq.com',])){
            $code = '123456';
        }

        // 不使用session，直接保存到数据库中
        // 先删除在重新赋值 避免多次生成 形成数组
        // Session::put($name, $code);
        // 发送短信是否满了
        $smsDb = new SiteSms();
        $where = [["email", '=', $email], ["ctime", '>=', strtotime("today")]];
        $lists = $smsDb->bangField(['email'])->getList($where, 0, 'id DESC');
        $lists = is_object($lists) ? $lists->toArray() : $lists;
        // 验证
        // TODO 分送时间10分钟内有效。一个号一天限制10次
        // TODO 间隔时间 60s
        if($lists){
            if(count($lists) >= $times){
                return $this->_returnFail('exceeded_the_number_can_be_sent_today');
            }
            if($lists[0]['ctime'] >= LARAVEL_TIME - $timeout){
                return $this->_returnFail('try_again_in_one_minute');
            }
        }


        //使用blade模板发送(引用的模板)
        // Mail::send(模板文件, [参数], function($message) use ($email) {});

        // 语言 与 模板
        /*$lang = $option->lang();
        if($lang == 'cn'){
            // 中文模板
            $emailTitle = 'ATW北美商业电讯 验证码';
            $emailTpl   = 'emails.code_email_cn';
            $emailName  = 'ATW 北美商業電訊 国内站点';
        } elseif($lang == 'en'){
            // 英文模板
            $emailTitle = 'ATW North America Business Telecommunications 验证码';
            $emailName  = 'ATW 北美商業電訊 英文站点';
            $emailTpl   = 'emails.code_email_en';
        } elseif($lang == 'tc'){
            // 繁体模板
            $emailTitle = 'ATW 北美商業電訊 验证码';
            $emailName  = 'ATW 北美商業電訊 繁体站点';
            $emailTpl   = 'emails.code_email_tc';
        }*/

        // 发送验证码
        if(!in_array($email, ['1758958047@qq.com',])){
            // 邮件只有英文版 英文模板
            $emailTitle = 'AISA TECH WIRE';
            $emailName  = 'AISA TECH WIRE';
            $emailTpl   = 'emails.code_email_en';

            // 发送邮件
            $form = 'lisen1004@qq.com';
            $form = 'svnewswire@gmail.com';
            Mail::alwaysFrom($form, $emailName);
            Mail::send($emailTpl, ['code' => $code], function($message) use ($email, $emailTitle) {
                $message->to($email)->subject($emailTitle);
            });
            if(Mail::failures()){
                return $this->_returnFail('email_send_failed');
            }
        }

        // 邮件发送成功，保存数据库
        $add = ["email" => $email, "code" => $code, "ip" => $option->getIp(), "status" => "0", "ctime" => LARAVEL_TIME];
        $smsDb->oneAdd($add);

        return $code;
    }

    // 忘记密码：第一步：验证要邮箱是否注册
    // 忘记密码：第二步：验证邮箱验证码 修改密码
    public function forgot()
    {
        $option    = $this->option();
        $email     = $option->getData('email', null, 'trim');
        $password  = $option->getData('password', null, 'trim');
        $password2 = $option->getData('password2', null, 'trim');
        $mobile    = $option->getData('mobile', null, 'trim');
        $captcha   = $option->getData('captcha', null, 'trim');  // 验证码（短信验证码）
        if(empty($email)){
            return $this->_returnFail('enter_the_email');
        }
        if(empty($password)){
            return $this->_returnFail('enter_the_password');
        }
        if(empty($password2)){
            return $this->_returnFail('enter_the_confirm_password');
        }
        if(empty($captcha)){
            return $this->_returnFail('enter_the_verification_code');
        }
        if($password != $password2){
            return $this->_returnFail('passwords_entered_twice_do_not_match');
        }

        // 验证验证码  session
        /*$session_name = 'session_code';
        $login_code   = Session::get($session_name);
        if((!empty($captcha)) && ($captcha != strtolower($login_code))){
            return $this->_returnFail('verification_code_is_wrong');
        }
        // 删除验证码
        Session::put($session_name, null);*/

        // 验证验证码  数据库
        if(!empty($captcha)){
            $codeWhere = [["email", '=', $email], ["ctime", '>=', strtotime("today")], ['status', '=', 0]];
            $smsDb     = new SiteSms();
            $lists     = $smsDb->isCache(false)->getList($codeWhere, 1, 'id DESC');
            if(empty($lists)){
                return $this->_returnFail('verification_code_is_wrong');
            }
            if($lists[0]['ctime'] + 600 < LARAVEL_TIME){
                return $this->_returnFail('verification_code_timed_out');
            }
            if($lists[0]['code'] != $captcha){
                return $this->_returnFail('verification_code_is_wrong');
            }

            // 使验证明失效
            $smsDb->where('id', $lists[0]['id'])->update(['status' => 1]);
        }

        // 查询用户信息
        $userDb = new User();
        $where  = [['email', '=', $email], ['status', '>=', 0]];
        $info   = $userDb->where($where)->first();
        if(empty($info)){
            return $this->_returnFail("email_has_not_exist");
        }

        // 修改密码
        $salt  = Str::random(4);
        $_pass = $userDb->add_md5($password, $salt);  // 密码
        $data  = ['salt' => $salt, 'password' => $_pass,];
        $info->fill($data);
        $info->save();

        return true;
    }


    ##########################################################################################################
    // openid登录（没有，则注册）
    public function openidLogin()
    {
        $option   = $this->option();
        $openid   = $option->getData('openid', null, 'trim');
        $mobile   = $option->getData('mobile', null, 'trim');
        $head_img = $option->getData('head_img', null, 'trim');
        $nickname = $option->getData('nickname', null, 'trim');
        if(empty($mobile)){
            return $this->_returnFail('enter_your_mobile_number');
        }
        if(empty($openid)){
            return $this->_returnFail('enter_the_openid');
        }

        // 获取登录的用户信息
        $userDb = new User();
        $where  = [['mobile', '=', $mobile], ['status', '>=', 0]];
        $info   = $userDb->isCache(true)->oneFind($where);
        if($info === false){
            return $this->_returnFail($userDb->getError());
        }
        if(empty($info)){
            // 如果没有 则注册
            $salt  = Str::random(4);
            $_pass = $userDb->add_md5(123456, $salt);  // 密码
            $data  = ['mobile' => $mobile, 'openid' => $openid, 'salt' => $salt, 'password' => $_pass,];
            if(!empty($head_img)){
                $data['head_img'] = $head_img;
            }
            if(!empty($nickname)){
                $data['nickname'] = $nickname;
            }
            $uid = $userDb->oneAdd($data);
            // 重新查询
            $info = $userDb->isCache(true)->oneFind(['mobile' => $mobile]);
        }

        // 返回
        //$user   = ['id' => $userId, 'nickname' => $info['email'], 'mobile' => $info['mobile']];
        $token  = Crypt::encryptString(json_encode($info, JSON_UNESCAPED_UNICODE));
        $result = ['token' => $token, 'user' => $info,];

        return $result;
    }


    // 小程序登录（没有，则注册）
    public function miniLogin()
    {
        $option = $this->option();
        $mobile = $option->getData('mobile', null, 'trim');
        $wxCode = $option->getData('wx_code', null, 'trim');  // 微信code用于获取openID
        if(empty($wxCode)){
            return $this->_returnFail('obtain_WeChat_code_first');
        }

        // 获取微信openID
        /**
         *  var userInfo = res.userInfo
         * var nickName = userInfo.nickName
         * var avatarUrl = userInfo.avatarUrl
         * var gender = userInfo.gender //性别 0：未知、1：男、2：女
         * var province = userInfo.province
         * var city = userInfo.city
         * var country = userInfo.country
         */
        $wx   = new OpenWx();
        $res  = $wx->getUserByMini($wxCode);
        $data = json_decode($res, true);

        Log::info('Request | 微信小程序请求openID返回 |', $data);
        $openid   = $data['openid'];
        $_key     = $data['session_key'];
        $head_img = $data['avatarUrl'];
        $nickname = $data['nickName'];
        $mobile   = $data['mobile'];

        // 判断微信是否存在
        $userDb = new User();
        $where  = [['openid', '=', $openid], ['status', '>=', 0]];
        $info   = $userDb->isCache(true)->oneFind($where);
        if(empty($info)){
            // 如果没有 则注册
            $salt  = Str::random(4);
            $_pass = $userDb->add_md5(123456, $salt);  // 密码
            $data  = ['mobile' => $mobile, 'openid' => $openid, 'salt' => $salt, 'password' => $_pass,];
            if(!empty($head_img)){
                $data['head_img'] = $head_img;
            }
            if(!empty($nickname)){
                $data['nickname'] = $nickname;
            }
            $uid = $userDb->oneAdd($data);
            // 重新查询
            $info = $userDb->isCache(true)->oneFind(['mobile' => $mobile]);
        }
        if($info['status'] === 0){
            return $this->_returnFail('you_have_been_disabled');
        }

        // 更新头像  和 名称
        $userId = $info['id'];
        $updata = ['last_ip' => $option->getIp(), 'last_time' => LARAVEL_TIME,];
        if((!empty($head_img)) && empty($info['head_img'])){
            $updata['head_img'] = $head_img;
        }
        if((!empty($nickname)) && empty($info['nickname'])){
            $updata['nickname'] = $nickname;
        }

        // 更新
        $rst = $userDb->where('id', $userId)->update($updata);
        if($rst === false){
            return $this->_returnFail($userDb->getError());
        }

        // 清理缓存
        $userDb->deleteCacheShow($info, $updata);

        // 返回
        //$user   = ['id' => $userId, 'nickname' => $info['email'], 'mobile' => $info['mobile']];
        $token  = Crypt::encryptString(json_encode($info, JSON_UNESCAPED_UNICODE));
        $result = ['token' => $token, 'user' => $info,];

        return $result;
    }


    // 微信公众号登录（没有，则注册）
    public function wxLogin()
    {
        $option = $this->option();
        $wxCode = $option->getData('wx_code', null, 'trim');  // 微信code用于获取openID
        if(empty($wxCode)){
            return $this->_returnFail('obtain_WeChat_code_first');
        }

        // 获取微信openID
        $wx   = new OpenWx();
        $res  = $wx->getAccessToken($wxCode);
        $data = json_decode($res, true);

        // 获取微信用户信息
        $openid = $data['openid'];
        $_token = $data['access_token'];
        $res    = $wx->getUser($_token, $openid);
        $data   = json_decode($res, true);


        Log::info('Request | 微信公众号请求用户信息返回 |', $data);
        $head_img = $data['avatarUrl'];
        $nickname = $data['nickName'];
        $mobile   = $data['mobile'];

        // 判断微信是否存在
        $userDb = new User();
        $where  = [['openid', '=', $openid], ['status', '>=', 0]];
        $info   = $userDb->isCache(true)->oneFind($where);
        if(empty($info)){
            // 如果没有 则注册
            $salt  = Str::random(4);
            $_pass = $userDb->add_md5(123456, $salt);  // 密码
            $data  = ['mobile' => $mobile, 'openid' => $openid, 'salt' => $salt, 'password' => $_pass,];
            if(!empty($head_img)){
                $data['head_img'] = $head_img;
            }
            if(!empty($nickname)){
                $data['nickname'] = $nickname;
            }
            $uid = $userDb->oneAdd($data);
            // 重新查询
            $info = $userDb->isCache(true)->oneFind(['mobile' => $mobile]);
        }
        if($info['status'] === 0){
            return $this->_returnFail('you_have_been_disabled');
        }

        // 更新头像  和 名称
        $userId = $info['id'];
        $updata = ['last_ip' => $option->getIp(), 'last_time' => LARAVEL_TIME,];
        if((!empty($head_img)) && empty($info['head_img'])){
            $updata['head_img'] = $head_img;
        }
        if((!empty($nickname)) && empty($info['nickname'])){
            $updata['nickname'] = $nickname;
        }

        // 更新
        $rst = $userDb->where('id', $userId)->update($updata);
        if($rst === false){
            return $this->_returnFail($userDb->getError());
        }

        // 清理缓存
        $userDb->deleteCacheShow($info, $updata);

        // 返回
        //$user   = ['id' => $userId, 'nickname' => $info['email'], 'mobile' => $info['mobile']];
        $token  = Crypt::encryptString(json_encode($info, JSON_UNESCAPED_UNICODE));
        $result = ['token' => $token, 'user' => $info,];

        return $result;
    }

    ##########################################################################################################
    // 假设你有一个WechatService类来处理微信相关的逻辑
    public function getSessionKeyAndOpenid($code)
    {
        $url      = "https://api.weixin.qq.com/sns/jscode2session";
        $params   = [
            'appid'      => config('wechat.mini_program.app_id'),
            'secret'     => config('wechat.mini_program.secret'),
            'js_code'    => $code,
            'grant_type' => 'authorization_code',
        ];
        $response = json_decode(file_get_contents($url.'?'.http_build_query($params)), true);
        if(isset($response['errcode'])){
            throw new Exception($response['errmsg']);
        }

        return $response;
    }

    // 获取小程序各种数据的 加密（所有数据来源于小程序传递过来的）
    public function encrypt($data, $iv, $key)
    {
        $block_size = 16;
        //补位处理
        $padding = $block_size - strlen($data) % $block_size;
        $data    .= str_repeat(chr($padding), $padding);
        //加密
        $encrypted = openssl_encrypt($data, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);

        return base64_encode($encrypted);
    }

    // 获取小程序各种数据的 解密（所有数据来源于小程序传递过来的）
    public function decrypt($encrypted, $iv, $key)
    {
        $aesKey    = base64_decode($key);
        $aesIV     = base64_decode($iv);
        $encrypted = base64_decode($encrypted);
        $decrypted = openssl_decrypt($encrypted, 'AES-128-CBC', $aesKey, OPENSSL_RAW_DATA, $aesIV);

        $block_size = 16;
        //去除补位信息
        $padding = ord(substr($decrypted, -1));
        if($padding < 1 || $padding > $block_size){
            $padding = 0;
        }
        $decrypted = substr($decrypted, 0, strlen($decrypted) - $padding);

        return $decrypted;
    }

    /**
     * 对明文进行加密
     * @param string $text 需要加密的明文
     * @return string 加密后的密文
     */
    public function encrypt2($text, $appid)
    {
        try{
            //获得16位随机字符串，填充到明文之前
            $random      = $this->getRandomStr();//"aaaabbbbccccdddd";
            $text        = $random.pack("N", strlen($text)).$text.$appid;
            $iv          = substr($this->key, 0, 16);
            $pkc_encoder = new PKCS7Encoder;
            $text        = $pkc_encoder->encode($text);
            $encrypted   = openssl_encrypt($text, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);

            return array(ErrorCode::$OK, $encrypted);
        } catch(Exception $e){
            //print $e;
            return array(ErrorCode::$EncryptAESError, null);
        }
    }

    /**
     * 对密文进行解密
     * @param string $encrypted 需要解密的密文
     * @return string 解密得到的明文
     */
    public function decrypt2($encrypted, $appid)
    {
        try{
            $iv        = substr($this->key, 0, 16);
            $decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
        } catch(Exception $e){
            return array(ErrorCode::$DecryptAESError, null);
        }
        try{
            //去除补位字符
            $pkc_encoder = new PKCS7Encoder;
            $result      = $pkc_encoder->decode($decrypted);
            //去除16位随机字符串,网络字节序和AppId
            if(strlen($result) < 16)
                return "";
            $content     = substr($result, 16, strlen($result));
            $len_list    = unpack("N", substr($content, 0, 4));
            $xml_len     = $len_list[1];
            $xml_content = substr($content, 4, $xml_len);
            $from_appid  = substr($content, $xml_len + 4);
            if(!$appid)
                $appid = $from_appid;
            //如果传入的appid是空的，则认为是订阅号，使用数据中提取出来的appid
        } catch(Exception $e){
            //print $e;
            return array(ErrorCode::$IllegalBuffer, null);
        }
        if($from_appid != $appid)
            return array(ErrorCode::$ValidateAppidError, null);

        //不注释上边两行，避免传入appid是错误的情况
        return array(0, $xml_content, $from_appid);
        //增加appid，为了解决后面加密回复消息的时候没有appid的订阅号会无法回复
    }

}


